﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<initializer_list>
#include<string>
#include<vector>
using namespace std;
//关于C++11新添加的参数列表初始化与新容器std::initializer_list
//1.C++11准备将所有类型对象均可统一采用{}进行初始化（包括内置类型），
//	而之前学习类的隐式类型转换部分时，也曾提到过，C++11之前就支持类类型使用{}（但需构造函数为单参数）
//	在C++11后，便也支持了类类型的多参数隐式类型转换
//  注：与此同时C++11规定允许使用{}进行初始化时省略“=”
//2.std::initializer_list，是C++11新引入的容器，翻译的话可以称作初始化列表，
//	但其与构造函数参数列表后的初始化列表不是一回事，事实上，之前我们就经常使用它，
//  它即为支持vector<int> v = { 1,2,3 }类似写法的一个作为构造函数参数的容器


//1.1：内置类型支持{}初始化
void test1()
{
	int a = { 1 };
	char c = { '1' };
	//……这里不再一一举例

	//支持{}初始化时省略'='
	double d{ 3.1415926 };
	bool i{ false };

	float arr[]{ 1.1,2.2,3.3,4.4,5.5,6.6 };
	for (const auto& e : arr)
	{
		cout << e << " ";
	}
	cout << endl;
}

//1.2：支持类类型多参数隐式类型转换（C++11前仅支持去除缺省值的单参数）
//（注：本质是先调用了带参构造将{}的内容隐式类型转换为A类型的临时对象，
//然后调用拷贝构造将临时对象拷贝给a对象，但现代编译器进行了优化，
//实际会直接使用参数对变量调用带参构造）
class A
{
public:
	A(int a, char b = 'a', double c = 3.14)
	{
		cout << "A(int a, char b, double c)" << endl;
	}
	A(const A& other)
	{
		cout << "A(const A& other)" << endl;
	}
};

void test2()
{
	//{}单参数隐式类型转换
	A a = { 1 };//"A(int a, char b, double c)"

	//{}多参数隐式类型转换
	A b = { 1,'b',2.71 };//"A(int a, char b, double c)"

	//{}隐式类型转换也可省略'='
	A c{ 1 };//"A(int a, char b, double c)"
	A d{ 1,'b',2.71 };//"A(int a, char b, double c)"

	//使用引用来判断是否生成了临时对象
	const A& ra = { 1 };//必须使用const&才可成功编译，即{}隐式类型转换生成的为临时对象
}

//2.1：std::initializer_list容器
//位于initializer_list头文件中，template<class T> class initializer_list;
//其接口包括size(),begin(),end()等，本质类似于一个数组，迭代器分别为指向首尾的指针
//常出现于容器的构造函数重载中，使容器得以{}进行多对象初始化操作（主要功能）
//构造函数内部可以理解为遍历initializer_list并进行依次插入（或拷贝）
//注：该容器为轻量级只读序列容器，用于实现列表初始化
void test3()
{
	//以vector容器举例：
	//本质是调用了构造重载vector (initializer_list<value_type> il,const allocator_type& alloc = allocator_type());
	vector<int> v1(initializer_list<int>{ 1, 2, 3, 4, 5, 6 });//initializer_list必须使用{}进行初始化操作

	//在正常使用时，一般会利用隐式类型转换，省略initializer_list，就变成了我们常见的形式：
	vector<int> v2({ 1, 2, 3, 4, 5, 6 });
}

//2.2：当同时具备initializer_list与带参构造函数重载，使用{}进行单个对象的初始化时，
//会“强烈优先”调用initializer_list构造，而非带参构造
// 
//原因在于C++标准规定的重载决议规则：​​
//只要编译器能够想方设法地将大括号内的内容解释为一个 std::initializer_list，
//它就会优先选择 std::initializer_list构造函数
//解决办法最推荐将{}换为()进行初始化，这样可以明确调用带参构造
template<class T>
class B
{
public:
	B(T a, char b = 'a', double c = 3.14)
	{
		cout << "B(T a, char b, double c)" << endl;
	}
	B(initializer_list<T> il)
	{
		cout << "B(initializer_list<T> il)" << endl;
	}
};
void test4()
{
	//B<int> b1{ 1 }等价于B<int> b1 = { 1 }
	B<int> b1{ 1 };//B(initializer_list<T> il)
	B<int> b2(1);// B(T a, char b, double c)
}
int main()
{
	//test1();
	//test2();
	//test3();
	test4();
	return 0;
}